use std::cell::RefCell;
use std::collections::HashMap;
use std::default::Default;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::rc::{Rc, Weak};
use std::sync::Arc;
use std::sync::atomic::{AtomicI32, Ordering};
use std::sync::mpsc::Receiver;
use std::time::Duration;

use eframe::emath::{Align, History, vec2};
use eframe::epaint::Color32;
use eframe::epaint::text::LayoutJob;
use egui::{Area, Frame, Galley, Id, Key, Layout, Order, Pos2, TextEdit, Ui, Vec2, Visuals};
use egui::style::ScrollStyle;
use egui_extras::{Column, TableBuilder, TableRow};
use lru_cache::LruCache;
use rand::{Rng, thread_rng};
use tokio::time::Instant;

use crate::filter::{FilterRequirement, get_cpu_usage, get_mem_usage, get_session_metadata, KeywordRequirement, KeywordType, LogFilter, MainEvent, start};
use crate::raw::{AllLog, AndroidLogLevel, Log};

/// We derive Deserialize/Serialize so we can persist app state on shutdown.
// #[derive(serde::Deserialize, serde::Serialize)]
// #[serde(default)] // if we add new fields, give them default values when deserializing old state
pub struct EnhancedLogcat {
    environment_broken: bool,
    receiver: Receiver<MainEvent>,
    last_render_time: Instant,
    session_list: Vec<(i32, Rc<RefCell<Pane>>)>,
    session_index: usize,
    frame_history: FrameHistory,
}

#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
enum ColType {
    Time,
    Level,
    Process,
    Pid,
    Tid,
    Tag,
    Message,
}

impl From<ColType> for &str {
    fn from(value: ColType) -> Self {
        match value {
            ColType::Time => { "Time" }
            ColType::Level => { "L" }
            ColType::Process => { "Process" }
            ColType::Pid => { "Pid" }
            ColType::Tid => { "Tid" }
            ColType::Tag => { "Tag" }
            ColType::Message => { "Content" }
        }
    }
}

impl From<AndroidLogLevel> for Color32 {

    fn from(value: AndroidLogLevel) -> Self {
        match value {
            AndroidLogLevel::VERBOSE => { Color32::from_rgb(0, 255, 188) }
            AndroidLogLevel::DEBUG => { Color32::DARK_BLUE }
            AndroidLogLevel::INFO => { Color32::DARK_GREEN }
            AndroidLogLevel::WARN => { Color32::from_rgb(255, 100, 0) }
            AndroidLogLevel::ERROR => { Color32::DARK_RED }
            AndroidLogLevel::FATAL => { Color32::from_rgb(161, 0x00, 255) }
        }
    }
}

impl ColType {
    fn get_str<'a>(&'a self, log: &'a Log) -> &str {
        match self {
            ColType::Time => { log.get_time() }
            ColType::Level => { Into::<&str>::into(log.get_level()) }
            ColType::Process => { log.get_process() }
            ColType::Pid => { log.get_pid_str() }
            ColType::Tid => { log.get_tid_str() }
            ColType::Tag => { log.get_tag() }
            ColType::Message => { log.get_content() }
        }
    }

    fn make_column(&self) -> Column {
        match self {
            ColType::Time => { Column::initial(125.0).range(100.0..=300.0) }
            ColType::Level => { Column::exact(20.0) }
            ColType::Process => { Column::initial(140.0).range(100.0..=360.0) }
            ColType::Pid => { Column::initial(40.0).range(30.0..=80.0) }
            ColType::Tid => { Column::initial(40.0).range(30.0..=80.0) }
            ColType::Tag => { Column::initial(140.0).range(100.0..=360.0) }
            ColType::Message => { Column::remainder().clip(true) }
        }
    }
}

struct Pane {
    shared_this: Weak<RefCell<Pane>>,
    is_left_leaf: bool,
    is_horizontal: bool,
    pane_id: i32,
    scroll_to_end: i32,
    show_log_count_in_detail: bool,
    filter: Option<LogFilter>,
    parent: Weak<RefCell<Pane>>,
    left: Option<Rc<RefCell<Pane>>>,
    right: Option<Rc<RefCell<Pane>>>,

    size_change_version: usize,
    multi_line_row_height_map: HashMap<usize, (f32/*height*/, usize/*version*/)>,

    process_color_cache: Rc<RefCell<LruCache<i32, Color32>>>,
    tab_color_array: [bool; 4],
    tab_show_array: [bool; 7],
    level_allow_array: [bool; 6],
    filter_condition: [EditKeyword; 3],// 0 -> process, 1 -> tag, 2 -> content
    col_width: HashMap<ColType, f32>,
    galley_lru_map: LruCache<usize, Arc<Galley>>,
}

#[derive(Clone)]
struct EditKeyword {
    keyword_type: KeywordType,
    text: String,
    keyword_list: Vec<UserKeyword>,
}

impl EditKeyword {
    fn new(keyword_type: KeywordType) -> Self {
        Self {
            keyword_type,
            text: String::new(),
            keyword_list: Vec::new(),
        }
    }
}

#[derive(Clone)]
struct UserKeyword {
    text: String,
    is_enabled: bool,
    is_case_insensitive: bool,
    is_whole_word: bool,
    is_excluded: bool,
}

impl Default for UserKeyword {
    fn default() -> Self {
        Self {
            text: String::new(),
            is_enabled: true,
            is_case_insensitive: false,
            is_whole_word: false,
            is_excluded: false,
        }
    }
}

struct FrameHistory {
    frame_times: History<f32>,
}

impl Default for FrameHistory {
    fn default() -> Self {
        let max_age: f32 = 1.0;
        let max_len = (max_age * 300.0).round() as usize;
        Self {
            frame_times: History::new(0..max_len, max_age),
        }
    }
}

impl FrameHistory {
    // Called first
    fn on_new_frame(&mut self, now: f64, previous_frame_time: Option<f32>) {
        let previous_frame_time = previous_frame_time.unwrap_or_default();
        if let Some(latest) = self.frame_times.latest_mut() {
            *latest = previous_frame_time; // rewrite history now that we know
        }
        self.frame_times.add(now, previous_frame_time); // projected
    }

    fn mean_frame_time(&self) -> f32 {
        self.frame_times.average().unwrap_or_default()
    }

    // fn fps(&self) -> f32 {
    //     1.0 / self.frame_times.mean_time_interval().unwrap_or_default()
    // }
}

static PANE_INDEX: AtomicI32 = AtomicI32::new(0);

impl Pane {
    /// 获取当前节点的兄弟节点（clone）
    fn get_sibling(&self) -> Option<Rc<RefCell<Pane>>> {
        if let Some(parent) = self.parent.upgrade() {
            if let (Some(left), Some(right)) = (parent.borrow().left.as_ref(), parent.borrow().right.as_ref()) {
                return if Rc::ptr_eq(&self.shared_this.upgrade().unwrap(), left) {
                    Some(right.clone())
                } else {
                    Some(left.clone())
                }
            }
        }
        None
    }

    /// 设置当前节点的左右子节点
    fn assign_children(&mut self, left: Option<Rc<RefCell<Pane>>>, right: Option<Rc<RefCell<Pane>>>) {
        self.left = left;
        self.right = right;
    }

    /// 获取当前节点的两个子节点（clone）
    fn get_children(&self) -> (Option<Rc<RefCell<Pane>>>, Option<Rc<RefCell<Pane>>>) {
        (self.left.as_ref().map(|left| left.clone()),
         self.right.as_ref().map(|right| right.clone()))
    }

    /// 二叉树新增叶子节点，不仅仅是添加叶子节点，还要把当前节点下移至叶子节点，换句话讲添加的是两个节点，一个新的叶子节点与一个新的父节点
    fn split(&mut self, horizontally: bool, root: &mut EnhancedLogcat) {
        self.galley_lru_map.clear();
        self.size_change_version += 1;

        let new_parent = Rc::new(RefCell::new(Self {
            is_left_leaf: self.is_left_leaf,
            is_horizontal: horizontally,
            ..Default::default()
        }));
        new_parent.borrow_mut().shared_this = Rc::downgrade(&new_parent);
        let new_sibling = Rc::new(RefCell::new(Self {
            is_left_leaf: false,
            filter: self.filter.as_ref().map(|filter| filter.clone()),
            parent: Rc::downgrade(&new_parent),
            show_log_count_in_detail: self.show_log_count_in_detail,

            process_color_cache: self.process_color_cache.clone(),
            tab_show_array: self.tab_show_array.clone(),
            tab_color_array: self.tab_color_array.clone(),
            level_allow_array: self.level_allow_array.clone(),
            filter_condition: self.filter_condition.clone(),
            ..Default::default()
        }));
        new_sibling.borrow_mut().shared_this = Rc::downgrade(&new_sibling);
        new_parent.borrow_mut().assign_children(self.shared_this.upgrade(), Some(new_sibling));
        if let Some(parent) = self.parent.upgrade() {
            let old_sibling = self.get_sibling();
            if self.is_left_leaf {
                parent.borrow_mut().assign_children(Some(new_parent.clone()), old_sibling);
            } else {
                parent.borrow_mut().assign_children(old_sibling, Some(new_parent.clone()));
            }
            new_parent.borrow_mut().parent = Rc::downgrade(&parent);
        } else {
            if let Some((_, root_pane)) = root.session_list.get_mut(root.session_index) {
                *root_pane = new_parent.clone();
            }
        }
        self.is_left_leaf = true;
        self.parent = Rc::downgrade(&new_parent);
    }

    /// 二叉树删除叶子节点，不仅仅是删除叶子节点，还要把当前兄弟节点上移取代原有父节点，换句话讲删除的是两个节点，一个叶子节点与一个父节点
    fn close(&mut self, root: &mut EnhancedLogcat) {
        let old_sibling = self.get_sibling();
        if old_sibling.is_none() {
            log::error!("can not close root pane!");
        } else if let Some(parent) = self.parent.upgrade() {
            let parent = parent.borrow();
            let grand_sibling = parent.get_sibling();
            let grand_parent = parent.parent.upgrade();
            if let Some(grand_parent) = grand_parent {
                if parent.is_left_leaf {
                    grand_parent.borrow_mut().assign_children(old_sibling, grand_sibling.map(|sibling| sibling.clone()));
                } else {
                    grand_parent.borrow_mut().assign_children(grand_sibling.map(|sibling| sibling.clone()), old_sibling);
                }
                self.is_left_leaf = parent.is_left_leaf;
                self.parent = Rc::downgrade(&grand_parent);
            } else {
                if let Some((_, root_pane)) = root.session_list.get_mut(root.session_index) {
                    *root_pane = old_sibling.unwrap();
                }
            }

            if let Some(filter) = self.filter.as_mut() {
                filter.stop_filtering();
            }
        } else {
            panic!("impossible situation")
        }
    }

    fn clear(&mut self) {
        if let Some(filter) = self.filter.as_mut() {
            filter.clear_from_ui();

            log::debug!("clear cache galley cache map size {}, multi row map size {}",
                self.galley_lru_map.len(), self.multi_line_row_height_map.len());
            self.galley_lru_map.clear();
            self.multi_line_row_height_map.clear();
        }
    }

    fn table_header_item(&mut self, row: &mut TableRow, col: ColType) {
        let (rect, _) = row.col(|ui| {
            ui.centered_and_justified(|ui| {
                match col {
                    ColType::Time | ColType::Pid | ColType::Tid => { ui.strong(Into::<&str>::into(col)); }
                    _ => { self.col_popup_ui(ui, col);}
                }
            });
        });
        if let Some(old_width) = self.col_width.insert(col, rect.width()) {
            if old_width as i32 != rect.width() as i32 {
                self.size_change_version += 1;
                self.galley_lru_map.clear();
            }
        }
    }

    fn table_body_item(&mut self, row: &mut TableRow, col: ColType, log: &Log) {
        row.col(|ui| {
            if col == ColType::Level && self.tab_color_array[0] {
                ui.painter().rect_filled(
                    ui.available_rect_before_wrap(),
                    0.0,
                    log.get_level(),
                );
            } else {
                let color_func = |key: i32| {
                    let mut color_cache_borrow = self.process_color_cache.borrow_mut();
                    let color: Color32 = if let Some(color) = color_cache_borrow.get_mut(&key) {
                        color.clone()
                    } else {
                        let mut random = thread_rng();
                        let red: u8 = random.gen_range(0..128);
                        let green: u8 = random.gen_range(0..128);
                        let blue: u8 = random.gen_range(0..128);
                        let new_color = Color32::from_rgb(red, green, blue);
                        color_cache_borrow.insert(key, new_color);
                        new_color
                    };
                    ui.painter().rect_filled(
                        ui.available_rect_before_wrap(),
                        0.0,
                        color,
                    );
                };
                if (col == ColType::Process || col == ColType::Pid) && self.tab_color_array[1] {
                    color_func(log.get_pid());
                } else if col == ColType::Tid && self.tab_color_array[2] {
                    color_func(log.get_tid());
                } else if col == ColType::Tag && self.tab_color_array[3] {
                    let mut hasher = DefaultHasher::new();
                    log.get_tag().hash(&mut hasher);
                    color_func(hasher.finish() as i32);
                }
            }
            let galley = self.measure_text(log, ui.ctx(), col);
            if col == ColType::Message {
                let response = ui.label(galley);
                response.context_menu(|ui| {
                    if ui.button("Highlight").clicked() {
                    }
                });
            } else {
                ui.with_layout(Layout::top_down(Align::Center), |ui| {
                    ui.label(galley);
                });
            }
        });
    }

    const POPUP_WIDTH: f32 = 400.0;

    fn col_popup_ui(&mut self, ui: &mut Ui, col_type: ColType) {
        let (keyword_index, keyword_count) = match col_type {
            ColType::Process => {
                (0, self.filter_condition[0].keyword_list.iter().fold(0, |acc, x| {
                    if x.is_enabled {
                        acc + 1
                    } else {
                        acc
                    }
                }))
            },
            ColType::Tag => {
                (1, self.filter_condition[1].keyword_list.iter().fold(0, |acc, x| {
                    if x.is_enabled {
                        acc + 1
                    } else {
                        acc
                    }
                }))
            },
            ColType::Message => {
                (2, self.filter_condition[2].keyword_list.iter().fold(0, |acc, x| {
                    if x.is_enabled {
                        acc + 1
                    } else {
                        acc
                    }
                }))
            },
            _ => (0, 0),
        };
        let response = if keyword_count == 0 {
            ui.button(Into::<&str>::into(col_type))
        } else {
            ui.button(format!("{}({})", Into::<&str>::into(col_type), keyword_count))
        };
        let popup_id = ui.make_persistent_id(Into::<&str>::into(col_type));
        if response.clicked() {
            ui.memory_mut(|mem| mem.toggle_popup(popup_id));
        }
        if ui.memory(|mem| mem.is_popup_open(popup_id)) {
            let request_focus =response.clicked();
            let pos = Pos2 {
                x: response.rect.min.x + (response.rect.width() - Self::POPUP_WIDTH) / 2.0,
                y: response.rect.max.y,
            };
            let area_response = Area::new(popup_id)
                .order(Order::Foreground)
                .fixed_pos(pos)
                .constrain(true)
                .show(ui.ctx(), |ui| {
                    Frame::popup(ui.style()).show(ui, |ui| {
                        match col_type {
                            ColType::Tag | ColType::Process | ColType::Message => {
                                self.keyword_filter_ui(ui, keyword_index, request_focus);
                            }
                            ColType::Level => { self.level_filter_ui(ui); }
                            _ => { todo!("not implemented") }
                        }
                    });
                })
                .response;

            if !response.clicked()
                && (ui.input(|i| i.key_pressed(Key::Escape)) || area_response.clicked_elsewhere()) {
                ui.memory_mut(|mem| mem.close_popup());
            }
        }
    }

    const LEVEL_LABEL: [AndroidLogLevel; 6] =
        [AndroidLogLevel::VERBOSE,
            AndroidLogLevel::DEBUG,
            AndroidLogLevel::INFO,
            AndroidLogLevel::WARN,
            AndroidLogLevel::ERROR,
            AndroidLogLevel::FATAL];
    const TAB_LIST: [ColType; 7] =
        [ColType::Time,
        ColType::Level,
        ColType::Process,
        ColType::Pid,
        ColType::Tid,
        ColType::Tag,
        ColType::Message];

    fn level_filter_ui(&mut self, ui: &mut Ui) {
        ui.vertical(|ui| {
            let mut update: bool = false;
            for (index, enabled) in self.level_allow_array.iter_mut().enumerate() {
                if ui.checkbox(enabled, Self::LEVEL_LABEL[index].get_description()).changed() {
                    update = true;
                }
            }
            if update {
                self.on_filter_update();
            }
        });
    }

    fn keyword_filter_ui(&mut self, ui: &mut Ui, filter_index: usize, request_focus: bool) {
        ui.vertical(|ui| {
            ui.spacing_mut().item_spacing.y = 5.0;
            let edit = &mut self.filter_condition[filter_index];
            let mut update = false;
            let initial_size = vec2(
                Self::POPUP_WIDTH,
                ui.spacing().interact_size.y,
            );
            edit.keyword_list.retain_mut(|keyword| {
                ui.allocate_ui_with_layout(initial_size.clone(), Layout::left_to_right(Align::Center), |ui| {
                    let mut keep: bool = true;
                    if ui.button("ｘ").clicked() {
                        keep = false;
                        update = true;
                    }
                    if ui.checkbox(&mut keyword.is_enabled, "").clicked() {
                        update = true;
                    }
                    ui.allocate_ui_with_layout(ui.available_size(), Layout::right_to_left(Align::Center), |ui| {
                        if ui.toggle_value(&mut keyword.is_excluded, "Exclude").clicked() {
                            update = true;
                        }
                        if ui.toggle_value(&mut keyword.is_whole_word, "Word").clicked() {
                            update = true;
                        }
                        if ui.toggle_value(&mut keyword.is_case_insensitive, "Case").clicked() {
                            update = true;
                        }
                        let user_output = TextEdit::singleline(&mut keyword.text)
                            .desired_width(ui.available_width()).show(ui);
                        if user_output.response.lost_focus() {
                            keep = !keyword.text.is_empty();
                            update = true;
                        }
                    });
                    keep
                }).inner
            });
            if edit.keyword_list.len() < 10 {
                ui.allocate_ui_with_layout(initial_size, Layout::right_to_left(Align::Center), |ui| {
                    let mut confirmed = false;
                    if ui.button("Add").clicked() {
                        confirmed = true;
                    }
                    let user_output = TextEdit::singleline(&mut edit.text)
                        .hint_text("Type keyword to filter")
                        .desired_width(f32::INFINITY)
                        .show(ui);
                    if request_focus {
                        ui.memory_mut(|mem| mem.request_focus(user_output.response.id));
                    } else if user_output.response.lost_focus() {
                        confirmed = true;
                    }
                    if confirmed && edit.text.len() > 0 {
                        let user_input = edit.text.clone();
                        edit.text.clear();
                        edit.keyword_list.push(UserKeyword {
                            text: user_input,
                            ..Default::default()
                        });
                        update = true;
                    }
                });
            } else {
                ui.label("Maximum 10 keywords");
            }
            if update {
                self.on_filter_update();
            }
        });
    }

    fn on_filter_update(&mut self) {
        let mut all_list: Vec<Vec<FilterRequirement>> = Vec::new();

        if self.level_allow_array.iter().any(|enable| !enable) {
            all_list.push(vec!(FilterRequirement::LogLevel(self.level_allow_array)));
        }

        for condition in &self.filter_condition {
            let mut keyword_requirement = Vec::new();
            for keyword in &condition.keyword_list {
                if keyword.is_enabled {
                    keyword_requirement.push(FilterRequirement::Keyword(KeywordRequirement::new(
                        condition.keyword_type, keyword.text.clone(), keyword.is_case_insensitive, keyword.is_whole_word, keyword.is_excluded)));
                }
            }
            if !keyword_requirement.is_empty() {
                all_list.push(keyword_requirement);
            }
        }

        self.filter.as_mut().unwrap().update(all_list);
    }

    fn measure_height(&mut self, log: &Arc<Log>, ctx: &egui::Context) -> f32 {
        if let Some((height, _)) = self.multi_line_row_height_map.get(&log.id) {
            *height
        } else {
            egui::TextStyle::Body.resolve(&ctx.style()).size
        }
    }

    fn measure_text(&mut self, log: &Log, ctx: &egui::Context, col: ColType) -> Arc<Galley> {
        if col == ColType::Message {
            if let Some(galley) = self.galley_lru_map.get_mut(&log.id) {
                return galley.clone();
            }
        }

        let constraint = *self.col_width.get(&col).unwrap();
        let font_id = ctx.style().text_styles.get(&egui::TextStyle::Body).unwrap().clone();
        let color = ctx.style().visuals.widgets.active.text_color();
        let galley = ctx.fonts(|fonts| {
            let mut layout_job = LayoutJob::simple(col.get_str(log).to_string(), font_id, color, constraint);
            if col != ColType::Message {
                layout_job.wrap.max_rows = 1;
            }
            fonts.layout_job(layout_job)
        });

        if col == ColType::Message {
            self.galley_lru_map.insert(log.id, galley.clone());
            let (version_match, existed_in_multi_map) = if let Some((_, version)) = self.multi_line_row_height_map.get(&log.id) {
                (*version == self.size_change_version, true)
            } else {
                (false, false)
            };
            if !version_match && (galley.rows.len() > 1 || existed_in_multi_map) {
                self.multi_line_row_height_map.insert(log.id, (galley.size().y, self.size_change_version));
            }
        }

        galley
    }
}

impl Default for Pane {
    fn default() -> Self {
        Self {
            shared_this: Weak::new(),
            is_left_leaf: true,
            is_horizontal: true,
            pane_id: PANE_INDEX.fetch_add(1, Ordering::SeqCst),
            scroll_to_end: 0,
            show_log_count_in_detail: false,
            filter: None,
            parent: Weak::new(),
            left: None,
            right: None,

            size_change_version: 0,
            multi_line_row_height_map: HashMap::new(),
            process_color_cache: Rc::new(RefCell::new(LruCache::new(100))),
            tab_color_array: [true, true, false, false],
            tab_show_array: std::array::from_fn(|_| true),
            level_allow_array: std::array::from_fn(|_| true),
            filter_condition: [EditKeyword::new(KeywordType::Process), EditKeyword::new(KeywordType::Tag), EditKeyword::new(KeywordType::Message)],
            col_width: HashMap::new(),
            galley_lru_map: LruCache::new(300),
        }
    }
}

impl EnhancedLogcat {
    pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
        cc.egui_ctx.style_mut(|style| {
            style.visuals = Visuals::dark();
            let body_style = style.text_styles.get_mut(&egui::TextStyle::Body);
            if let Some(body_style) = body_style {
                body_style.size = 16.0;
            }
            style.spacing.scroll = ScrollStyle::solid();
        });

        let (tx, rx) = std::sync::mpsc::channel();
        start(cc.egui_ctx.clone(), tx);

        Self {
            environment_broken: false,
            receiver: rx,
            last_render_time: Instant::now(),
            session_list: Vec::new(),
            session_index: 0,
            frame_history: FrameHistory {
                frame_times: History::new(0..300, 1.0)
            }
        }
    }

    fn pane_inflate(&mut self, pane: &Rc<RefCell<Pane>>, id: Id, current_depth: u8, ui: &mut Ui, first_pane: &mut bool) {
        let (left, right) = pane.borrow().get_children();
        if let (Some(left), Some(right)) = (left, right) {
            let left_id = Id::new(left.borrow().pane_id);
            let right_id = Id::new(right.borrow().pane_id);
            if pane.borrow().is_horizontal {
                let total_width = ui.available_width();
                egui::SidePanel::left(left_id)
                    .frame(Default::default())
                    .resizable(true)
                    .min_width(total_width * 0.2)
                    .max_width(total_width * 0.8)
                    .default_width(total_width * 0.5)
                    .show_inside(ui, |ui| {
                        self.pane_inflate(&left, left_id.with("inside"), current_depth + 1, ui, first_pane);
                        ui.allocate_space(ui.available_size());
                    });
            } else {
                let total_height = ui.available_height();
                egui::TopBottomPanel::top(left_id)
                    .resizable(true)
                    .frame(Default::default())
                    .min_height(total_height * 0.2)
                    .max_height(total_height * 0.8)
                    .default_height(total_height * 0.5)
                    .show_inside(ui, |ui| {
                        self.pane_inflate(&left, left_id.with("inside"), current_depth + 1, ui, first_pane);
                        ui.allocate_space(ui.available_size());
                    });
            }
            egui::CentralPanel::default().frame(Default::default()).show_inside(ui, |ui| {
                self.pane_inflate(&right, right_id, current_depth + 1, ui, first_pane);
            });
        } else {
            let log_one_frame = pane.borrow().filter.as_ref()
                .expect("missing filter on leaf pane?").get_log_one_frame();
            log_one_frame.acquire_current_log(|log| {
                self.pane_ui(pane, id, current_depth, ui, first_pane, log);
            });
        }
    }

    fn print_pane(depth: u8, intend: String, pane: &Rc<RefCell<Pane>>) {
        let (left, right) = pane.borrow().get_children();
        if let (Some(left), Some(right)) = (left, right) {
            log::info!("{intend}depth:{depth} {} addr:{:?}",
                if pane.borrow().is_horizontal {"horizontal"} else {"vertical"}, pane.as_ptr());
            log::info!("{intend}left==>");
            Self::print_pane(depth + 1, intend.clone() + "    ", &left);
            log::info!("{intend}right==>");
            Self::print_pane(depth + 1, intend + "    ", &right);
        } else {
            log::info!("{intend}leaf depth:{depth} addr:{:?}", pane.as_ptr());
        }
    }

    fn pane_ui(&mut self, pane: &Rc<RefCell<Pane>>, id: Id, current_depth: u8, ui: &mut Ui, first_pane: &mut bool, frame_log_slice: &[Arc<Log>]) {
        egui::TopBottomPanel::top(id).frame(Default::default()).show_inside(ui, |ui| {
            egui::menu::bar(ui, |ui| {
                if ui.button("Clear").clicked() {
                    pane.borrow_mut().clear();
                    // Self::print_pane(0, "".to_string(), &self.root_pane);
                }
                if ui.button("End").clicked() {
                    pane.borrow_mut().scroll_to_end = 5;
                    // Self::print_pane(0, "".to_string(), &self.root_pane);
                }
                ui.menu_button("Tab", |ui| {
                    let mut pane_borrowed = pane.borrow_mut();
                    for (index, col) in Pane::TAB_LIST.iter().enumerate() {
                        if *col != ColType::Message {
                            ui.checkbox(&mut pane_borrowed.tab_show_array[index], Into::<&str>::into(*col));
                        }
                    }
                });
                ui.menu_button("Color", |ui| {
                    let mut pane_borrowed = pane.borrow_mut();
                    ui.checkbox(&mut pane_borrowed.tab_color_array[0], Into::<&str>::into(ColType::Level));
                    ui.checkbox(&mut pane_borrowed.tab_color_array[1], Into::<&str>::into(ColType::Process));
                    ui.checkbox(&mut pane_borrowed.tab_color_array[2], Into::<&str>::into(ColType::Tid));
                    ui.checkbox(&mut pane_borrowed.tab_color_array[3], Into::<&str>::into(ColType::Tag));
                });
                if current_depth < 2 {
                    ui.menu_button("Split", |ui| {
                        let parent = pane.borrow().parent.upgrade();
                        if let Some(_) = parent {
                            if ui.button("Close").clicked() {
                                ui.close_menu();
                                pane.borrow_mut().close(self);
                                // Self::print_pane(0, "".to_string(), &self.root_pane);
                            }
                        }
                        if ui.button("Split Horizontal").clicked() {
                            ui.close_menu();
                            pane.borrow_mut().split(true, self);
                            // Self::print_pane(0, "".to_string(), &self.root_pane);
                        }
                        if ui.button("Split Vertical").clicked() {
                            ui.close_menu();
                            pane.borrow_mut().split(false, self);
                            // Self::print_pane(0, "".to_string(), &self.root_pane);
                        }
                    });
                } else {
                    if ui.button("Close").clicked() {
                        pane.borrow_mut().close(self);
                        // Self::print_pane(0, "".to_string(), &self.root_pane);
                    }
                }
                if *first_pane {
                    ui.menu_button("Session", |ui| {
                        if self.session_list.len() > 1 {
                            for (index, (session, _)) in self.session_list.iter().enumerate() {
                                ui.radio_value(&mut self.session_index, index, format!("Session {session}"));
                            }
                            if self.session_index == self.session_list.len() - 1 {
                                if ui.button("Close Others").clicked() {
                                    self.session_list.drain(0..self.session_index);
                                    self.session_index = 0;
                                    ui.close_menu();
                                    // Self::print_pane(0, "".to_string(), &self.root_pane);
                                }
                            } else {
                                if ui.button("Close Current").clicked() {
                                    self.session_list.remove(self.session_index);
                                    self.session_index = self.session_list.len() - 1;
                                    ui.close_menu();
                                    // Self::print_pane(0, "".to_string(), &self.root_pane);
                                }
                            }
                        }
                        if self.session_index == self.session_list.len() - 1 || self.session_list.len() == 1 {
                            if ui.button("Start New Session").clicked() {
                                if let Some(filter) = pane.borrow().filter.as_ref() {
                                    filter.start_new_session();
                                }
                                ui.close_menu();
                                // Self::print_pane(0, "".to_string(), &self.root_pane);
                            }
                        }
                    });
                    *first_pane = false;
                }

                ui.allocate_ui_with_layout(Vec2 {
                    x: ui.available_size().x,
                    y: ui.available_size_before_wrap().y,
                }, Layout::right_to_left(Align::Center), |ui| {
                    let mut pane_borrowed = pane.borrow_mut();
                    let size = frame_log_slice.len();
                    ui.add_space(8.0);
                    let count_description;
                    if size < 1000 || pane_borrowed.show_log_count_in_detail {
                        count_description = size.to_string();
                    } else if size < 10000 {
                        count_description = format!("{:.1}k", size as f32 / 1000.0);
                    } else {
                        count_description = format!("{:.1}w", size as f32 / 10000.0);
                    }
                    ui.toggle_value(&mut pane_borrowed.show_log_count_in_detail, count_description);
                });
            });
        });

        ui.vertical(|ui| {
            self.table_ui(ui, pane, frame_log_slice);
        });
    }

    fn table_ui(&mut self, ui: &mut Ui, pane: &Rc<RefCell<Pane>>, frame_log_slice: &[Arc<Log>]) {
        let mut table = TableBuilder::new(ui)
            .striped(true)
            .resizable(true)
            .stick_to_bottom(true)
            .max_scroll_height(f32::MAX)
            .cell_layout(Layout::left_to_right(Align::Center))
            .sense(egui::Sense::click());

        {
            let mut pane_borrowed = pane.borrow_mut();

            for (index, col) in Pane::TAB_LIST.iter().enumerate() {
                if pane_borrowed.tab_show_array[index] {
                    table = table.column(col.make_column());
                }
            }

            let scroll_to_end = pane_borrowed.scroll_to_end;
            if scroll_to_end > 0 {
                table = table.scroll_to_row(usize::MAX, None);
                pane_borrowed.scroll_to_end -= 1;
            }
        }

        table.header(20.0, |mut header| {
            let mut pane_borrowed = pane.borrow_mut();
            for (index, col) in Pane::TAB_LIST.iter().enumerate() {
                if pane_borrowed.tab_show_array[index] {
                    pane_borrowed.table_header_item(&mut header, col.clone());
                }
            }
        }).body(|mut body| {

            let row_builder = |mut row: TableRow| {
                let log = frame_log_slice.get(row.index()).unwrap();
                let log_resolved = log.resolved;
                let mut pane_borrowed = pane.borrow_mut();
                for (index, col) in Pane::TAB_LIST.iter().enumerate() {
                    if pane_borrowed.tab_show_array[index] {
                        if log_resolved || *col == ColType::Message {
                            pane_borrowed.table_body_item(&mut row, col.clone(), &log);
                        } else {
                            row.col(|_| {
                            });
                        }
                    }
                }
            };
            // body.rows(text_height, all_log.len(), row_builder);
            let ctx = body.ui_mut().ctx().clone();
            // let text_height = egui::TextStyle::Body
            //     .resolve(ui.style())
            //     .size
            //     .max(ui.spacing().interact_size.y);
            body.heterogeneous_rows(frame_log_slice.iter().map(|log| {
                let mut pane_borrowed = pane.borrow_mut();
                pane_borrowed.measure_height(log, &ctx)
            }), row_builder);
        });
    }
}

impl eframe::App for EnhancedLogcat {
    fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
        while let Ok(event) = self.receiver.try_recv() {
            match event {
                MainEvent::NewSession(filter) => {
                    let session_id = filter.session_id;
                    log::info!("NewSession received: {}", session_id);
                    let root_pane = Rc::new(RefCell::new(Pane {
                        filter: Some(filter),
                        .. Default::default()
                    }));
                    root_pane.borrow_mut().shared_this = Rc::downgrade(&root_pane);

                    self.session_list.push((session_id, root_pane));
                    self.session_index = self.session_list.len() - 1;
                }
                MainEvent::EnvironmentBroken => {
                    self.environment_broken = true;
                }
            }
        }

        if self.environment_broken {
            egui::CentralPanel::default().show(ctx, |ui| {
                ui.centered_and_justified(|ui| {
                    ui.label("Launch adb failed, check your environment and restart again");
                });
            });
            return;
        }

        self.frame_history
            .on_new_frame(ctx.input(|i| i.time), frame.info().cpu_usage);

        egui::TopBottomPanel::bottom("logo&cpu")
            .frame(Frame {
                inner_margin: egui::Margin::same(5.0),
                ..Frame::side_top_panel(ctx.style().as_ref())
            })
            .show(ctx, |ui| {
                ui.horizontal_centered(|ui| {
                    ui.style_mut().spacing.item_spacing.x = 16.0;
                    ui.small(format!("CPU usage:  {:.1}%",
                                     get_cpu_usage() as f32 / 10.0));
                    ui.small(format!("Render:  {:.2} ms / frame",
                                     1e3 * self.frame_history.mean_frame_time()));
                    // ui.small(format!("FPS:  {:.1}", self.frame_history.fps()));
                    ui.small(format!("Memory: {} Mb",  get_mem_usage()));

                    if !self.session_list.is_empty() && self.session_index == self.session_list.len() - 1 {
                        ui.allocate_ui_with_layout(Vec2 {
                            x: ui.available_size().x,
                            y: ui.available_size_before_wrap().y,
                        }, Layout::right_to_left(Align::Center), |ui| {
                            let session = self.session_list.get(self.session_index).map_or(-1, |(session, _)| { *session });
                            if let Some((usage, eta)) = get_session_metadata(session) {
                                ui.small(format!("Usage:  {:.2}%",  usage * 100.0));
                                if eta >= 3600 {
                                    ui.small(format!("ETA:  {}h::{}m", eta / 3600, (eta % 3600) / 60));
                                } else {
                                    ui.small(format!("ETA:  {}m::{}s", eta / 60, eta % 60));
                                }
                            } else {
                                ui.small("Usage:  0.00%");
                                ui.small("ETA:  --::--");
                            }
                        });
                    }
                });
            });

        egui::CentralPanel::default().show(ctx, |ui| {
            if self.session_list.len() > 0 {
                let (_, root_pane) = self.session_list.get(self.session_index).unwrap().clone();
                let id = root_pane.borrow().pane_id;
                let mut first_pane: bool = true;
                self.pane_inflate(&root_pane, Id::new(id),0, ui, &mut first_pane);
            } else {
                ui.centered_and_justified(|ui| {
                    ui.label("waiting for adb device");
                });
            }
        });
    }

    /// Called by the frame work to save state before shutdown.
    fn save(&mut self, storage: &mut dyn eframe::Storage) {
        // eframe::set_value(storage, eframe::APP_KEY, self);
    }

    fn persist_egui_memory(&self) -> bool {
        false
    }
}